"""
个性化推荐系统服务实现

提供高级个性化推荐功能，包括：
- 基于偏好的推荐算法
- 上下文感知推荐逻辑
- 推荐效果评估机制
- 协同过滤推荐
- 内容基础推荐
"""
import json
import math
from typing import List, Dict, Any, Optional, Tuple, Set
from datetime import datetime, timedelta
from dataclasses import dataclass, asdict, replace, field
from collections import defaultdict, Counter
from enum import Enum

from ..models.analysis_models import (
    UserBehavior, UserPreferences, Context, Recommendations, 
    InterfaceConfig, PreferenceChange
)
from .preference_analysis_service import PreferenceAnalysisService
from .user_behavior_service import UserBehaviorService


class RecommendationType(Enum):
    """推荐类型枚举"""
    PREFERENCE_BASED = "preference_based"
    CONTEXT_AWARE = "context_aware"
    COLLABORATIVE = "collaborative"
    CONTENT_BASED = "content_based"
    HYBRID = "hybrid"


class RecommendationStrategy(Enum):
    """推荐策略枚举"""
    EXPLORATION = "exploration"  # 探索新功能
    EXPLOITATION = "exploitation"  # 利用已知偏好
    BALANCED = "balanced"  # 平衡探索和利用


@dataclass
class RecommendationItem:
    """推荐项目"""
    item_id: str = ""
    item_type: str = ""  # method, feature, workflow, tutorial, etc.
    title: str = ""
    description: str = ""
    category: str = ""
    difficulty_level: str = "intermediate"  # beginner, intermediate, advanced
    estimated_time_minutes: int = 30
    prerequisites: List[str] = None
    tags: List[str] = None
    popularity_score: float = 0.5
    quality_score: float = 0.5
    
    def __post_init__(self):
        if self.prerequisites is None:
            self.prerequisites = []
        if self.tags is None:
            self.tags = []


@dataclass
class RecommendationResult:
    """推荐结果"""
    item: RecommendationItem
    score: float
    confidence: float
    reasoning: List[str]
    recommendation_type: RecommendationType
    context_factors: Dict[str, Any]


@dataclass
class RecommendationEvaluation:
    """推荐评估结果"""
    user_id: str
    recommendation_id: str
    item_id: str
    was_clicked: bool = False
    was_completed: bool = False
    user_rating: Optional[float] = None
    time_spent_seconds: float = 0.0
    user_feedback: Optional[str] = None
    evaluation_date: datetime = None
    
    def __post_init__(self):
        if self.evaluation_date is None:
            self.evaluation_date = datetime.now()


class PersonalizedRecommendationService:
    """个性化推荐系统服务"""
    
    def __init__(self, 
                 preference_service: Optional[PreferenceAnalysisService] = None,
                 behavior_service: Optional[UserBehaviorService] = None):
        self.preference_service = preference_service or PreferenceAnalysisService()
        self.behavior_service = behavior_service or UserBehaviorService()
        
        # 推荐项目库
        self.recommendation_items: Dict[str, RecommendationItem] = {}
        self.item_categories: Dict[str, List[str]] = defaultdict(list)
        
        # 推荐历史和评估
        self.recommendation_history: Dict[str, List[RecommendationResult]] = defaultdict(list)
        self.recommendation_evaluations: Dict[str, List[RecommendationEvaluation]] = defaultdict(list)
        
        # 用户相似度矩阵（用于协同过滤）
        self.user_similarity_matrix: Dict[Tuple[str, str], float] = {}
        
        # 推荐配置
        self.recommendation_config = {
            'max_recommendations': 10,
            'min_confidence_threshold': 0.3,
            'diversity_weight': 0.2,
            'novelty_weight': 0.15,
            'popularity_weight': 0.1,
            'context_weight': 0.3,
            'preference_weight': 0.4,
            'collaborative_weight': 0.15,
            'exploration_rate': 0.2  # 20%的推荐用于探索新内容
        }
        
        # 初始化推荐项目库
        self._initialize_recommendation_items()
    
    def _initialize_recommendation_items(self):
        """初始化推荐项目库"""
        # 方法类推荐项目
        methods = [
            ("topic_analysis", "主题分析", "智能分析研究主题的复杂度和范围", "research_planning", "beginner", 30),
            ("literature_search", "文献检索", "高效检索和筛选相关学术文献", "literature_review", "beginner", 45),
            ("experiment_design", "实验设计", "基于文献分析设计科学实验方案", "experiment", "intermediate", 60),
            ("data_analysis", "数据分析", "自动化数据处理和统计分析", "data_processing", "intermediate", 90),
            ("visualization", "数据可视化", "生成专业的图表和可视化结果", "data_processing", "beginner", 30),
            ("quality_assessment", "质量评估", "评估研究质量并提供改进建议", "quality_control", "advanced", 45),
            ("machine_learning", "机器学习", "应用机器学习算法进行数据分析", "advanced_analysis", "advanced", 120),
            ("statistical_analysis", "统计分析", "进行高级统计检验和分析", "advanced_analysis", "intermediate", 75),
            ("parameter_optimization", "参数优化", "自动优化实验和模型参数", "optimization", "advanced", 90),
            ("knowledge_graph", "知识图谱", "构建和分析研究领域知识图谱", "knowledge_management", "advanced", 150)
        ]
        
        for item_id, title, description, category, difficulty, time_est in methods:
            item = RecommendationItem(
                item_id=item_id,
                item_type="method",
                title=title,
                description=description,
                category=category,
                difficulty_level=difficulty,
                estimated_time_minutes=time_est,
                tags=[category, difficulty, "method"],
                popularity_score=0.6,
                quality_score=0.8
            )
            self.recommendation_items[item_id] = item
            self.item_categories[category].append(item_id)
        
        # 功能类推荐项目
        features = [
            ("collaborative_editing", "协作编辑", "多人实时协作编辑研究文档", "collaboration", "beginner", 20),
            ("version_control", "版本控制", "管理研究项目的版本历史", "project_management", "intermediate", 30),
            ("automated_reporting", "自动报告", "自动生成研究报告和论文", "reporting", "intermediate", 60),
            ("citation_management", "引用管理", "自动管理和格式化文献引用", "literature_review", "beginner", 25),
            ("peer_review", "同行评议", "参与或组织同行评议流程", "collaboration", "advanced", 90),
            ("research_templates", "研究模板", "使用预定义的研究项目模板", "project_management", "beginner", 15)
        ]
        
        for item_id, title, description, category, difficulty, time_est in features:
            item = RecommendationItem(
                item_id=item_id,
                item_type="feature",
                title=title,
                description=description,
                category=category,
                difficulty_level=difficulty,
                estimated_time_minutes=time_est,
                tags=[category, difficulty, "feature"],
                popularity_score=0.5,
                quality_score=0.7
            )
            self.recommendation_items[item_id] = item
            self.item_categories[category].append(item_id)
        
        # 学习资源类推荐项目
        tutorials = [
            ("getting_started_guide", "入门指南", "系统功能的基础入门教程", "tutorial", "beginner", 45),
            ("advanced_techniques", "高级技巧", "掌握系统的高级使用技巧", "tutorial", "advanced", 90),
            ("best_practices", "最佳实践", "学习研究项目的最佳实践", "tutorial", "intermediate", 60),
            ("case_studies", "案例研究", "通过实际案例学习系统应用", "tutorial", "intermediate", 75),
            ("api_documentation", "API文档", "学习系统API的使用方法", "tutorial", "advanced", 120),
            ("troubleshooting_guide", "故障排除", "解决常见问题的指南", "tutorial", "beginner", 30)
        ]
        
        for item_id, title, description, category, difficulty, time_est in tutorials:
            item = RecommendationItem(
                item_id=item_id,
                item_type="tutorial",
                title=title,
                description=description,
                category=category,
                difficulty_level=difficulty,
                estimated_time_minutes=time_est,
                tags=[category, difficulty, "tutorial", "learning"],
                popularity_score=0.4,
                quality_score=0.9
            )
            self.recommendation_items[item_id] = item
            self.item_categories[category].append(item_id)
    
    async def generate_recommendations(self, 
                                     user_id: str, 
                                     context: Context,
                                     strategy: RecommendationStrategy = RecommendationStrategy.BALANCED,
                                     max_items: Optional[int] = None) -> List[RecommendationResult]:
        """生成个性化推荐"""
        try:
            max_items = max_items or self.recommendation_config['max_recommendations']
            
            # 获取用户偏好
            if user_id not in self.preference_service.user_preferences:
                await self.preference_service.update_preference_model(user_id)
            
            user_preferences = self.preference_service.user_preferences.get(user_id)
            if not user_preferences:
                return await self._generate_default_recommendations(context, max_items)
            
            # 生成不同类型的推荐
            preference_recommendations = await self._generate_preference_based_recommendations(
                user_id, user_preferences, context
            )
            
            context_recommendations = await self._generate_context_aware_recommendations(
                user_id, context, user_preferences
            )
            
            collaborative_recommendations = await self._generate_collaborative_recommendations(
                user_id, user_preferences
            )
            
            content_recommendations = await self._generate_content_based_recommendations(
                user_id, user_preferences, context
            )
            
            # 合并和排序推荐
            all_recommendations = []
            all_recommendations.extend(preference_recommendations)
            all_recommendations.extend(context_recommendations)
            all_recommendations.extend(collaborative_recommendations)
            all_recommendations.extend(content_recommendations)
            
            # 去重和排序
            unique_recommendations = self._deduplicate_recommendations(all_recommendations)
            
            # 应用推荐策略
            final_recommendations = await self._apply_recommendation_strategy(
                unique_recommendations, strategy, max_items
            )
            
            # 增加多样性
            diverse_recommendations = self._ensure_diversity(final_recommendations, max_items)
            
            # 记录推荐历史
            self.recommendation_history[user_id].extend(diverse_recommendations)
            
            return diverse_recommendations
            
        except Exception as e:
            print(f"生成个性化推荐失败: {e}")
            return await self._generate_default_recommendations(context, max_items)
    
    async def _generate_preference_based_recommendations(self, 
                                                       user_id: str,
                                                       preferences: UserPreferences,
                                                       context: Context) -> List[RecommendationResult]:
        """基于偏好的推荐"""
        recommendations = []
        
        # 基于偏好方法推荐
        for method in preferences.preferred_methods[:5]:
            if method in self.recommendation_items:
                item = self.recommendation_items[method]
                
                # 计算推荐分数
                score = self._calculate_preference_score(item, preferences, context)
                confidence = 0.8
                
                reasoning = [f"基于您的使用历史，您经常使用{item.title}"]
                
                recommendation = RecommendationResult(
                    item=item,
                    score=score,
                    confidence=confidence,
                    reasoning=reasoning,
                    recommendation_type=RecommendationType.PREFERENCE_BASED,
                    context_factors={'preference_match': True}
                )
                recommendations.append(recommendation)
        
        # 基于学习风格推荐
        if preferences.learning_style in self.preference_service.learning_styles:
            style_actions = self.preference_service.learning_styles[preferences.learning_style]
            
            for action in style_actions[:3]:
                matching_items = [item for item in self.recommendation_items.values()
                                if action in item.tags or action in item.item_id]
                
                for item in matching_items[:2]:  # 限制每个动作的推荐数量
                    score = self._calculate_learning_style_score(item, preferences.learning_style)
                    confidence = 0.7
                    
                    reasoning = [f"根据您的{preferences.learning_style}学习风格推荐"]
                    
                    recommendation = RecommendationResult(
                        item=item,
                        score=score,
                        confidence=confidence,
                        reasoning=reasoning,
                        recommendation_type=RecommendationType.PREFERENCE_BASED,
                        context_factors={'learning_style_match': True}
                    )
                    recommendations.append(recommendation)
        
        # 基于专业水平推荐
        expertise_items = [item for item in self.recommendation_items.values()
                          if item.difficulty_level == preferences.expertise_level]
        
        for item in expertise_items[:3]:
            score = self._calculate_expertise_score(item, preferences.expertise_level)
            confidence = 0.75
            
            reasoning = [f"根据您的{preferences.expertise_level}专业水平推荐"]
            
            recommendation = RecommendationResult(
                item=item,
                score=score,
                confidence=confidence,
                reasoning=reasoning,
                recommendation_type=RecommendationType.PREFERENCE_BASED,
                context_factors={'expertise_match': True}
            )
            recommendations.append(recommendation)
        
        return recommendations
    
    async def _generate_context_aware_recommendations(self,
                                                    user_id: str,
                                                    context: Context,
                                                    preferences: UserPreferences) -> List[RecommendationResult]:
        """上下文感知推荐"""
        recommendations = []
        
        # 基于当前任务推荐
        task_related_items = [item for item in self.recommendation_items.values()
                             if context.current_task in item.tags or 
                             context.current_task in item.category]
        
        for item in task_related_items[:3]:
            score = self._calculate_context_score(item, context)
            confidence = 0.8
            
            reasoning = [f"与您当前的{context.current_task}任务相关"]
            
            recommendation = RecommendationResult(
                item=item,
                score=score,
                confidence=confidence,
                reasoning=reasoning,
                recommendation_type=RecommendationType.CONTEXT_AWARE,
                context_factors={'task_relevance': True}
            )
            recommendations.append(recommendation)
        
        # 基于时间约束推荐
        if context.time_constraints.get('urgent', False):
            quick_items = [item for item in self.recommendation_items.values()
                          if item.estimated_time_minutes <= 30]
            
            for item in quick_items[:2]:
                score = self._calculate_urgency_score(item, context)
                confidence = 0.9
                
                reasoning = ["考虑到时间紧急，推荐快速完成的任务"]
                
                recommendation = RecommendationResult(
                    item=item,
                    score=score,
                    confidence=confidence,
                    reasoning=reasoning,
                    recommendation_type=RecommendationType.CONTEXT_AWARE,
                    context_factors={'time_sensitive': True}
                )
                recommendations.append(recommendation)
        
        # 基于可用资源推荐
        if 'high_performance_computing' in context.available_resources:
            advanced_items = [item for item in self.recommendation_items.values()
                             if item.difficulty_level == 'advanced' and 
                             'advanced_analysis' in item.category]
            
            for item in advanced_items[:2]:
                score = self._calculate_resource_score(item, context)
                confidence = 0.7
                
                reasoning = ["基于您的高性能计算资源推荐"]
                
                recommendation = RecommendationResult(
                    item=item,
                    score=score,
                    confidence=confidence,
                    reasoning=reasoning,
                    recommendation_type=RecommendationType.CONTEXT_AWARE,
                    context_factors={'resource_match': True}
                )
                recommendations.append(recommendation)
        
        # 基于用户目标推荐
        for goal in context.user_goals[:3]:
            goal_related_items = [item for item in self.recommendation_items.values()
                                 if goal in item.tags or goal in item.description.lower()]
            
            for item in goal_related_items[:1]:  # 每个目标推荐1个
                score = self._calculate_goal_score(item, goal)
                confidence = 0.75
                
                reasoning = [f"有助于实现您的{goal}目标"]
                
                recommendation = RecommendationResult(
                    item=item,
                    score=score,
                    confidence=confidence,
                    reasoning=reasoning,
                    recommendation_type=RecommendationType.CONTEXT_AWARE,
                    context_factors={'goal_alignment': True}
                )
                recommendations.append(recommendation)
        
        return recommendations
    
    async def _generate_collaborative_recommendations(self,
                                                    user_id: str,
                                                    preferences: UserPreferences) -> List[RecommendationResult]:
        """协同过滤推荐"""
        recommendations = []
        
        try:
            # 找到相似用户
            similar_users = await self._find_similar_users(user_id, preferences)
            
            if not similar_users:
                return recommendations
            
            # 获取相似用户的偏好项目
            similar_user_items = defaultdict(float)
            
            for similar_user_id, similarity_score in similar_users[:5]:
                if similar_user_id in self.preference_service.user_preferences:
                    similar_prefs = self.preference_service.user_preferences[similar_user_id]
                    
                    for method in similar_prefs.preferred_methods[:3]:
                        if method in self.recommendation_items:
                            similar_user_items[method] += similarity_score
            
            # 过滤掉用户已经偏好的项目
            user_preferred_methods = set(preferences.preferred_methods)
            
            for item_id, collaborative_score in similar_user_items.items():
                if item_id not in user_preferred_methods and collaborative_score > 0.3:
                    item = self.recommendation_items[item_id]
                    
                    score = collaborative_score * 0.8  # 协同过滤权重
                    confidence = min(0.8, collaborative_score)
                    
                    reasoning = ["基于相似用户的使用偏好推荐"]
                    
                    recommendation = RecommendationResult(
                        item=item,
                        score=score,
                        confidence=confidence,
                        reasoning=reasoning,
                        recommendation_type=RecommendationType.COLLABORATIVE,
                        context_factors={'collaborative_score': collaborative_score}
                    )
                    recommendations.append(recommendation)
            
        except Exception as e:
            print(f"协同过滤推荐失败: {e}")
        
        return recommendations[:3]  # 限制协同推荐数量
    
    async def _generate_content_based_recommendations(self,
                                                    user_id: str,
                                                    preferences: UserPreferences,
                                                    context: Context) -> List[RecommendationResult]:
        """基于内容的推荐"""
        recommendations = []
        
        # 基于用户偏好的项目特征推荐相似项目
        user_preferred_items = [self.recommendation_items[method] 
                               for method in preferences.preferred_methods 
                               if method in self.recommendation_items]
        
        if not user_preferred_items:
            return recommendations
        
        # 提取用户偏好的特征
        preferred_categories = Counter()
        preferred_tags = Counter()
        preferred_difficulty = Counter()
        
        for item in user_preferred_items:
            preferred_categories[item.category] += 1
            preferred_tags.update(item.tags)
            preferred_difficulty[item.difficulty_level] += 1
        
        # 找到相似的未使用项目
        unused_items = [item for item in self.recommendation_items.values()
                       if item.item_id not in preferences.preferred_methods]
        
        for item in unused_items:
            content_score = self._calculate_content_similarity(
                item, preferred_categories, preferred_tags, preferred_difficulty
            )
            
            if content_score > 0.4:  # 相似度阈值
                confidence = min(0.8, content_score)
                
                reasoning = ["基于您偏好的内容特征推荐相似项目"]
                
                recommendation = RecommendationResult(
                    item=item,
                    score=content_score,
                    confidence=confidence,
                    reasoning=reasoning,
                    recommendation_type=RecommendationType.CONTENT_BASED,
                    context_factors={'content_similarity': content_score}
                )
                recommendations.append(recommendation)
        
        # 按相似度排序并返回前几个
        recommendations.sort(key=lambda x: x.score, reverse=True)
        return recommendations[:4]
    
    async def _find_similar_users(self, user_id: str, preferences: UserPreferences) -> List[Tuple[str, float]]:
        """找到相似用户"""
        similar_users = []
        
        for other_user_id, other_preferences in self.preference_service.user_preferences.items():
            if other_user_id != user_id:
                similarity = await self.preference_service._calculate_preference_similarity(
                    preferences, other_preferences
                )
                
                if similarity > 0.5:  # 相似度阈值
                    similar_users.append((other_user_id, similarity))
        
        # 按相似度排序
        similar_users.sort(key=lambda x: x[1], reverse=True)
        return similar_users
    
    def _calculate_preference_score(self, item: RecommendationItem, 
                                  preferences: UserPreferences, 
                                  context: Context) -> float:
        """计算偏好匹配分数"""
        score = 0.0
        
        # 基础分数
        score += item.quality_score * 0.3
        score += item.popularity_score * 0.2
        
        # 专业水平匹配
        if item.difficulty_level == preferences.expertise_level:
            score += 0.3
        elif (preferences.expertise_level == "advanced" and item.difficulty_level == "intermediate") or \
             (preferences.expertise_level == "intermediate" and item.difficulty_level == "beginner"):
            score += 0.15
        
        # 学习风格匹配
        if preferences.learning_style in item.tags:
            score += 0.2
        
        return min(1.0, score)
    
    def _calculate_learning_style_score(self, item: RecommendationItem, learning_style: str) -> float:
        """计算学习风格匹配分数"""
        base_score = item.quality_score * 0.5
        
        if learning_style in item.tags:
            base_score += 0.4
        
        return min(1.0, base_score)
    
    def _calculate_expertise_score(self, item: RecommendationItem, expertise_level: str) -> float:
        """计算专业水平匹配分数"""
        base_score = item.quality_score * 0.4
        
        if item.difficulty_level == expertise_level:
            base_score += 0.5
        elif expertise_level == "advanced" and item.difficulty_level == "intermediate":
            base_score += 0.3
        elif expertise_level == "intermediate" and item.difficulty_level == "beginner":
            base_score += 0.2
        
        return min(1.0, base_score)
    
    def _calculate_context_score(self, item: RecommendationItem, context: Context) -> float:
        """计算上下文匹配分数"""
        score = item.quality_score * 0.3
        
        # 任务相关性
        if context.current_task in item.category or context.current_task in item.tags:
            score += 0.4
        
        # 项目类型匹配
        if context.project_type in item.tags:
            score += 0.3
        
        return min(1.0, score)
    
    def _calculate_urgency_score(self, item: RecommendationItem, context: Context) -> float:
        """计算紧急情况下的分数"""
        base_score = item.quality_score * 0.4
        
        # 时间效率加分
        if item.estimated_time_minutes <= 30:
            base_score += 0.5
        elif item.estimated_time_minutes <= 60:
            base_score += 0.3
        
        return min(1.0, base_score)
    
    def _calculate_resource_score(self, item: RecommendationItem, context: Context) -> float:
        """计算资源匹配分数"""
        score = item.quality_score * 0.4
        
        # 高级资源匹配高级功能
        if 'high_performance_computing' in context.available_resources and item.difficulty_level == 'advanced':
            score += 0.4
        
        # GPU资源匹配机器学习
        if 'GPU' in context.available_resources and 'machine_learning' in item.item_id:
            score += 0.3
        
        return min(1.0, score)
    
    def _calculate_goal_score(self, item: RecommendationItem, goal: str) -> float:
        """计算目标匹配分数"""
        base_score = item.quality_score * 0.4
        
        if goal.lower() in item.description.lower():
            base_score += 0.4
        elif goal in item.tags:
            base_score += 0.3
        
        return min(1.0, base_score)
    
    def _calculate_content_similarity(self, item: RecommendationItem,
                                    preferred_categories: Counter,
                                    preferred_tags: Counter,
                                    preferred_difficulty: Counter) -> float:
        """计算内容相似度"""
        similarity = 0.0
        
        # 类别相似度
        if item.category in preferred_categories:
            similarity += 0.4 * (preferred_categories[item.category] / sum(preferred_categories.values()))
        
        # 标签相似度
        tag_similarity = 0.0
        for tag in item.tags:
            if tag in preferred_tags:
                tag_similarity += preferred_tags[tag] / sum(preferred_tags.values())
        
        similarity += 0.4 * min(1.0, tag_similarity)
        
        # 难度相似度
        if item.difficulty_level in preferred_difficulty:
            similarity += 0.2 * (preferred_difficulty[item.difficulty_level] / sum(preferred_difficulty.values()))
        
        return min(1.0, similarity)
    
    def _deduplicate_recommendations(self, recommendations: List[RecommendationResult]) -> List[RecommendationResult]:
        """去重推荐结果"""
        seen_items = set()
        unique_recommendations = []
        
        # 按分数排序
        recommendations.sort(key=lambda x: x.score, reverse=True)
        
        for rec in recommendations:
            if rec.item.item_id not in seen_items:
                seen_items.add(rec.item.item_id)
                unique_recommendations.append(rec)
        
        return unique_recommendations
    
    async def _apply_recommendation_strategy(self, 
                                           recommendations: List[RecommendationResult],
                                           strategy: RecommendationStrategy,
                                           max_items: int) -> List[RecommendationResult]:
        """应用推荐策略"""
        if strategy == RecommendationStrategy.EXPLOITATION:
            # 利用策略：优先推荐高置信度的项目
            recommendations.sort(key=lambda x: x.confidence * x.score, reverse=True)
            
        elif strategy == RecommendationStrategy.EXPLORATION:
            # 探索策略：优先推荐新颖的项目
            for rec in recommendations:
                if rec.item.popularity_score < 0.3:  # 低流行度 = 高新颖性
                    rec.score *= 1.2  # 提升新颖项目的分数
            
            recommendations.sort(key=lambda x: x.score, reverse=True)
            
        else:  # BALANCED
            # 平衡策略：混合利用和探索
            exploitation_count = int(max_items * 0.7)
            exploration_count = max_items - exploitation_count
            
            # 按置信度排序获取利用项目
            exploitation_recs = sorted(recommendations, 
                                     key=lambda x: x.confidence * x.score, 
                                     reverse=True)[:exploitation_count]
            
            # 按新颖性排序获取探索项目
            remaining_recs = [r for r in recommendations if r not in exploitation_recs]
            exploration_recs = sorted(remaining_recs,
                                    key=lambda x: (1 - x.item.popularity_score) * x.score,
                                    reverse=True)[:exploration_count]
            
            recommendations = exploitation_recs + exploration_recs
        
        return recommendations[:max_items]
    
    def _ensure_diversity(self, recommendations: List[RecommendationResult], max_items: int) -> List[RecommendationResult]:
        """确保推荐的多样性"""
        if len(recommendations) <= max_items:
            return recommendations
        
        diverse_recommendations = []
        used_categories = set()
        used_types = set()
        
        # 首先选择不同类别和类型的项目
        for rec in recommendations:
            if (len(diverse_recommendations) < max_items and
                rec.item.category not in used_categories and
                rec.item.item_type not in used_types):
                
                diverse_recommendations.append(rec)
                used_categories.add(rec.item.category)
                used_types.add(rec.item.item_type)
        
        # 填充剩余位置
        remaining_slots = max_items - len(diverse_recommendations)
        remaining_recs = [r for r in recommendations if r not in diverse_recommendations]
        
        diverse_recommendations.extend(remaining_recs[:remaining_slots])
        
        return diverse_recommendations
    
    async def _generate_default_recommendations(self, context: Context, max_items: int) -> List[RecommendationResult]:
        """生成默认推荐（当没有用户偏好时）"""
        default_recommendations = []
        
        # 推荐高质量和流行的项目
        popular_items = sorted(self.recommendation_items.values(),
                              key=lambda x: x.popularity_score * x.quality_score,
                              reverse=True)
        
        for item in popular_items[:max_items]:
            recommendation = RecommendationResult(
                item=item,
                score=item.popularity_score * item.quality_score,
                confidence=0.5,
                reasoning=["基于项目流行度和质量的推荐"],
                recommendation_type=RecommendationType.CONTENT_BASED,
                context_factors={'default_recommendation': True}
            )
            default_recommendations.append(recommendation)
        
        return default_recommendations
    
    async def evaluate_recommendation(self, user_id: str, recommendation_id: str, 
                                    evaluation: RecommendationEvaluation) -> bool:
        """评估推荐效果"""
        try:
            evaluation.user_id = user_id
            evaluation.recommendation_id = recommendation_id
            
            self.recommendation_evaluations[user_id].append(evaluation)
            
            # 更新推荐项目的统计信息
            if evaluation.item_id in self.recommendation_items:
                item = self.recommendation_items[evaluation.item_id]
                
                # 简单的评分更新逻辑
                if evaluation.user_rating is not None:
                    # 更新质量分数（简化的移动平均）
                    current_score = item.quality_score
                    new_score = (current_score * 0.9) + (evaluation.user_rating * 0.1)
                    item.quality_score = max(0.0, min(1.0, new_score))
                
                if evaluation.was_clicked:
                    # 增加流行度
                    item.popularity_score = min(1.0, item.popularity_score + 0.01)
            
            return True
            
        except Exception as e:
            print(f"评估推荐效果失败: {e}")
            return False
    
    async def get_recommendation_metrics(self, user_id: str, days: int = 30) -> Dict[str, Any]:
        """获取推荐效果指标"""
        try:
            cutoff_date = datetime.now() - timedelta(days=days)
            
            # 获取指定时间范围内的评估数据
            recent_evaluations = [
                eval for eval in self.recommendation_evaluations.get(user_id, [])
                if eval.evaluation_date > cutoff_date
            ]
            
            if not recent_evaluations:
                return {'error': '没有足够的评估数据'}
            
            total_recommendations = len(recent_evaluations)
            clicked_recommendations = sum(1 for eval in recent_evaluations if eval.was_clicked)
            completed_recommendations = sum(1 for eval in recent_evaluations if eval.was_completed)
            
            # 计算指标
            click_through_rate = clicked_recommendations / total_recommendations if total_recommendations > 0 else 0
            completion_rate = completed_recommendations / total_recommendations if total_recommendations > 0 else 0
            
            # 平均评分
            rated_evaluations = [eval for eval in recent_evaluations if eval.user_rating is not None]
            average_rating = sum(eval.user_rating for eval in rated_evaluations) / len(rated_evaluations) if rated_evaluations else 0
            
            # 平均使用时间
            time_spent_evaluations = [eval for eval in recent_evaluations if eval.time_spent_seconds > 0]
            average_time_spent = sum(eval.time_spent_seconds for eval in time_spent_evaluations) / len(time_spent_evaluations) if time_spent_evaluations else 0
            
            # 推荐类型分布
            type_distribution = Counter(
                self._get_recommendation_type_by_item_id(eval.item_id) 
                for eval in recent_evaluations
            )
            
            metrics = {
                'period_days': days,
                'total_recommendations': total_recommendations,
                'click_through_rate': click_through_rate,
                'completion_rate': completion_rate,
                'average_rating': average_rating,
                'average_time_spent_minutes': average_time_spent / 60,
                'recommendation_type_distribution': dict(type_distribution),
                'user_satisfaction': self._calculate_user_satisfaction(recent_evaluations)
            }
            
            return metrics
            
        except Exception as e:
            print(f"获取推荐指标失败: {e}")
            return {'error': '推荐指标计算失败'}
    
    def _get_recommendation_type_by_item_id(self, item_id: str) -> str:
        """根据项目ID获取推荐类型"""
        if item_id in self.recommendation_items:
            return self.recommendation_items[item_id].item_type
        return "unknown"
    
    def _calculate_user_satisfaction(self, evaluations: List[RecommendationEvaluation]) -> float:
        """计算用户满意度"""
        if not evaluations:
            return 0.0
        
        satisfaction_score = 0.0
        total_weight = 0.0
        
        for eval in evaluations:
            weight = 1.0
            
            # 点击加分
            if eval.was_clicked:
                satisfaction_score += 0.3 * weight
            
            # 完成加分
            if eval.was_completed:
                satisfaction_score += 0.4 * weight
            
            # 评分加分
            if eval.user_rating is not None:
                satisfaction_score += (eval.user_rating / 5.0) * 0.3 * weight
            
            total_weight += weight
        
        return satisfaction_score / total_weight if total_weight > 0 else 0.0
    
    async def get_recommendation_insights(self, user_id: str) -> Dict[str, Any]:
        """获取推荐洞察"""
        try:
            insights = {
                'user_id': user_id,
                'analysis_date': datetime.now().isoformat(),
                'recommendation_patterns': {},
                'preference_evolution': {},
                'effectiveness_trends': {}
            }
            
            # 分析推荐模式
            user_history = self.recommendation_history.get(user_id, [])
            if user_history:
                type_counts = Counter(rec.recommendation_type.value for rec in user_history)
                insights['recommendation_patterns'] = {
                    'most_common_type': type_counts.most_common(1)[0] if type_counts else None,
                    'type_distribution': dict(type_counts),
                    'total_recommendations': len(user_history)
                }
            
            # 分析偏好演变
            if user_id in self.preference_service.preference_history:
                history = self.preference_service.preference_history[user_id]
                if len(history) >= 2:
                    initial_prefs = history[0]
                    current_prefs = history[-1]
                    
                    insights['preference_evolution'] = {
                        'learning_style_changed': initial_prefs.learning_style != current_prefs.learning_style,
                        'expertise_level_changed': initial_prefs.expertise_level != current_prefs.expertise_level,
                        'method_preferences_stability': len(set(initial_prefs.preferred_methods).intersection(set(current_prefs.preferred_methods))) / max(1, len(set(initial_prefs.preferred_methods).union(set(current_prefs.preferred_methods))))
                    }
            
            # 分析效果趋势
            evaluations = self.recommendation_evaluations.get(user_id, [])
            if len(evaluations) >= 5:
                recent_evaluations = evaluations[-5:]
                earlier_evaluations = evaluations[-10:-5] if len(evaluations) >= 10 else evaluations[:-5]
                
                recent_ctr = sum(1 for eval in recent_evaluations if eval.was_clicked) / len(recent_evaluations)
                earlier_ctr = sum(1 for eval in earlier_evaluations if eval.was_clicked) / len(earlier_evaluations) if earlier_evaluations else 0
                
                insights['effectiveness_trends'] = {
                    'click_through_rate_trend': 'improving' if recent_ctr > earlier_ctr else 'declining' if recent_ctr < earlier_ctr else 'stable',
                    'recent_ctr': recent_ctr,
                    'earlier_ctr': earlier_ctr
                }
            
            return insights
            
        except Exception as e:
            print(f"获取推荐洞察失败: {e}")
            return {'error': '推荐洞察分析失败'}
    
    async def export_recommendation_data(self, user_id: str) -> Dict[str, Any]:
        """导出推荐数据"""
        try:
            export_data = {
                'user_id': user_id,
                'export_date': datetime.now().isoformat(),
                'recommendation_history': [],
                'recommendation_evaluations': []
            }
            
            # 导出推荐历史
            if user_id in self.recommendation_history:
                for rec in self.recommendation_history[user_id]:
                    rec_data = {
                        'item_id': rec.item.item_id,
                        'item_title': rec.item.title,
                        'score': rec.score,
                        'confidence': rec.confidence,
                        'recommendation_type': rec.recommendation_type.value,
                        'reasoning': rec.reasoning
                    }
                    export_data['recommendation_history'].append(rec_data)
            
            # 导出评估数据
            if user_id in self.recommendation_evaluations:
                for eval in self.recommendation_evaluations[user_id]:
                    eval_data = asdict(eval)
                    eval_data['evaluation_date'] = eval.evaluation_date.isoformat()
                    export_data['recommendation_evaluations'].append(eval_data)
            
            return export_data
            
        except Exception as e:
            print(f"导出推荐数据失败: {e}")
            return {'error': '推荐数据导出失败'}
    
    async def delete_recommendation_data(self, user_id: str) -> bool:
        """删除推荐数据"""
        try:
            if user_id in self.recommendation_history:
                del self.recommendation_history[user_id]
            
            if user_id in self.recommendation_evaluations:
                del self.recommendation_evaluations[user_id]
            
            # 清理用户相似度矩阵中的相关数据
            keys_to_remove = [key for key in self.user_similarity_matrix.keys() 
                             if user_id in key]
            for key in keys_to_remove:
                del self.user_similarity_matrix[key]
            
            return True
            
        except Exception as e:
            print(f"删除推荐数据失败: {e}")
            return False